#include"fa.h"

using std::istream;
using std::pair;
using std::set;
using std::string;
using std::make_pair;

NameStorage FA::initNames() {
	NameStorage res;
	res.addName("");
	return res;
}

NameStorage FA::names = initNames();

pair<pair<unsigned, char>, unsigned> FA::extractRuleFromStream(istream & in) {
	string str;
	getline(in, str);
	unsigned pos = str . find_first_of(':');
  //  std::cout << "str "<< str << std::endl;
	if (pos != string::npos) {
		string left = extractAlNum(str . substr(0, pos)), right = extractAlNum(str . substr(pos + 1));
		unsigned commaguard = names.addName(left);
		return make_pair(make_pair(commaguard, right[0]), names.addName(right . substr(1)));
	}
	else {
		pos = str . find_first_of('~');
		string left = extractAlNum(str . substr(0, pos)), right = extractAlNum(str . substr(pos + 1));
		unsigned commaguard = names.addName(left);
		return make_pair(make_pair(commaguard, (char)0), names.addName(right));
	}
}

string FA::extractAlNum(string const & str) {
	string res;
	for(unsigned i = 0; i < str.length(); i++)
		if (isalnum(str[i]))
			res.push_back(str[i]);
	return res;
}

set<unsigned> FA::setUnion(set<unsigned> const & a, set<unsigned> const & b) {
	set<unsigned> big = (a . size() > b . size()) ? a : b,
				small = (a . size() > b . size()) ? b : a;
	set<unsigned>::const_iterator it = small . begin();
	set<unsigned> res = big;
	for( ; it != small . end(); ++it )
		res . insert(*it);
	return res;
}

set<unsigned> FA::setIntersection(set<unsigned> const & a, set<unsigned> const & b) {
	set<unsigned> big = (a . size() > b . size()) ? a : b,
				small = (a . size() > b . size()) ? b : a;
	set<unsigned>::const_iterator it = small . begin();
	set<unsigned> res;
	for( ; it != small . end(); ++it )
		if (big . find(*it) != big . end())
			res . insert(*it);
	return res;
}

set<unsigned> FA::setDifference(std::set<unsigned> const & a, std::set<unsigned> const & b) {
	set<unsigned>::const_iterator it = a . begin();
	set<unsigned> res;
	for ( ; it != a.end(); ++it ) {
		if (b.find(*it) == b.end()) res.insert(*it);	
	}
	return res;
}

string FA::concatName(set<unsigned> const & state) {
	string res;
	set<unsigned>::const_iterator it = state . begin();
	for( ; it != state . end(); ++it )
		res += names[*it];
	return res;
}

bool CompareSet::operator()(set<unsigned> const & a, set<unsigned> const & b) {
	if (a . size() != b . size())
		return (a . size() < b . size());
	set<unsigned>::const_iterator ita = a . begin(), itb = b . begin();
	while((ita != a . end()) && (*ita)==(*itb)) {
		++ita; ++itb;
	}
	return (ita != a . end()) && ((*ita) < (*itb));
}
